#include "LayoutPage.h"
#include "oled.h"
#include <string.h> 
#include "shdl.h"


namespace MircoUi {	
    void vItem::follow(vItem* item){
        Linklist_prepend((tPtr*)&follower, SHDL_OFFSETOF(vItem,follower_list_next), item);
    }
    void vItem::initUi(LayoutPage* root,sVec2 diff, uint8 h, uint8 follow_type){
        this->root_page = root; // 设置根页面
        this->diff = diff; // 设置相对起始点的位置
        this->h = h;
        this->mode = 1;
        this->follow_type = follow_type;
        this->follower_list_next = nullptr; // 初始化下一个节点为nullptr
        this->follower = nullptr; // 初始化跟随者为nullptr
    }
    void vItem::initUi(LayoutPage* root,vItem* followee,int16 x, int16 y, uint8 h,uint8 follow_type){
        initUi(root,sVec2(x,y), h, follow_type);
        followee->follow(this);
    }
    void vItem::initUi(LayoutPage* root,int16 x, int16 y, uint8 h,uint8 follow_type){
        initUi(root,sVec2(x,y), h, follow_type);        
        Linklist_prepend((tPtr*)&(root->follower_list), SHDL_OFFSETOF(vItem,follower_list_next), this);
    }    
    void vItem::changed() {
        if(update_flag == eUpdateType::no_change) {
            update_flag = eUpdateType::changed; 
            Linklist_prepend((tPtr*)&(root_page->update_list), SHDL_OFFSETOF(vItem,update_list_next), this);
        }        
    }
}

namespace MircoUi {
    void LayoutPage::init(){   
        follower_list = nullptr;    
        update_list = nullptr; // 初始化变量列表为空  
        eventCB = nullptr; // 初始化事件回调为空
        status = 0; // 页面状态初始化为未绘制
    }
    void LayoutPage::drawItem(vItem* item) {
        if (item == nullptr) return;
        sVec2 s = item->draw(item->abs_point);
        if((status ==0)||(item->size != s)) {
            item->size = s; // 更新项目的大小
            sVec2 ep = item->abs_point + s; // 计算结束点
            uint16 count = 0;
            vItem* current = item->follower;            
            while (current != nullptr) {
                if(current->follow_type == 0) { //跟随在右侧
                    current->abs_point.x = ep.x + current->diff.x;
                    current->abs_point.y = item->abs_point.y + current->diff.y;
                } else if(current->follow_type == 1) { //跟随在下方
                    current->abs_point.x = item->abs_point.x + current->diff.x;
                    current->abs_point.y = ep.y + current->diff.y;
                }
                drawItem(current);
                current = current->follower_list_next;
                if(count++ > 1024) { break; }// 防止死循环
            }   

        }         
    }
    int LayoutPage::foreachDraw(tPtr node, void* tag) {
        vItem* current = (vItem*)node;
        LayoutPage* page = (LayoutPage*)tag;
        current->abs_point.x = current->diff.x;
        current->abs_point.y = current->diff.y;
        page->drawItem(current);        
        return 0; // 继续遍历
    }
    void LayoutPage::refresh() {        
        if(this->status == 0) { // 如果页面未绘制
            OLED_Clear(); // 如果是第一次更新，清空OLED屏幕
            Linklist_foreach((tPtr*)&follower_list, SHDL_OFFSETOF(vItem,follower_list_next), foreachDraw, this);
            this->status = 1;
            OLED_Refresh();
        }else{      
            uint16 count = 0;
            byte has_update = 0;      
            while (count<1024) { //防止死循环
                count++;
                vItem* current = (vItem*) Linklist_removeFirst((tPtr*)&update_list, SHDL_OFFSETOF(vItem,update_list_next));
                if(current == nullptr){
                    break; // 如果没有更多更新项，退出循环
                }
                if(current->update_flag == eUpdateType::changed) {
                    current->update_flag = eUpdateType::no_change; 
                    has_update = 1; // 标记有更新
                    drawItem(current); 
                }
            }
            if(has_update) {
                OLED_Refresh(); // 如果有更新，刷新OLED屏幕
            }
        }
    }

    void LayoutPage::onEvent(uint32 event_id, uint32 event_par) {
        if(eventCB) {
            eventCB(event_id, event_par);
        }
        if(event_id == eEvent::TICK) {

        } else if(event_id == eEvent::ENTER_PAGE) {
        } else if(event_id == eEvent::EXIT_PAGE) {
            status = 0; // 重置页面状态为未绘制
        }
    }
}

